/**
 * Copyright 2015 ABSir's Studio
 * 
 * All right reserved
 *
 * Create on 2015年4月9日 下午4:12:36
 */
package com.absir.appserv.system.service;

import java.io.Serializable;
import java.nio.channels.SocketChannel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.absir.appserv.system.helper.HelperEncrypt;
import com.absir.appserv.system.master.MasterSessionResolver;
import com.absir.context.core.ContextUtils;
import com.absir.core.kernel.KernelByte;
import com.absir.core.kernel.KernelLang.PropertyFilter;
import com.absir.server.socket.IServerContext;
import com.absir.server.socket.InputSocketImpl;
import com.absir.server.socket.ServerContext;
import com.absir.server.socket.SocketBuffer;
import com.absir.server.socket.SocketChannelContext;

/**
 * @author absir
 *
 */
public class MasterSessionResolverImpl implements MasterSessionResolver {

	/** LOGGER */
	protected static final Logger LOGGER = LoggerFactory.getLogger(MasterSessionResolverImpl.class);

	/** propertyFilter */
	protected PropertyFilter propertyFilter;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.absir.appserv.master.MasterSessionResolver#setSessionFilters(java
	 * .lang.String[], java.lang.String[])
	 */
	@Override
	public void setSessionFilters(String[] includes, String[] excludes) {
		if (includes != null && includes.length > 0) {
			propertyFilter = new PropertyFilter();
			for (String include : includes) {
				propertyFilter.inlcude(include);
			}
		}

		if (excludes != null && excludes.length > 0) {
			if (propertyFilter == null) {
				propertyFilter = new PropertyFilter();
			}

			for (String exclude : excludes) {
				propertyFilter.inlcude(exclude);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.absir.server.socket.resolver.SocketSessionResolver#accept(java.nio
	 * .channels.SocketChannel, com.absir.server.socket.ServerContext)
	 */
	@Override
	public boolean accept(final SocketChannel socketChannel, final ServerContext serverContext) throws Throwable {
		if (propertyFilter != null && !propertyFilter.isMatchPath(socketChannel.socket().getInetAddress().toString())) {
			return false;
		}

		ContextUtils.getThreadPoolExecutor().execute(new Runnable() {

			@Override
			public void run() {
				InputSocketImpl.writeByteBuffer(MasterService.ME.getChannelResolver(), socketChannel,
						KernelByte.getLengthBytes(socketChannel.hashCode()));
			}
		});

		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.absir.server.socket.resolver.SocketSessionResolver#register(java.
	 * nio.channels.SocketChannel, com.absir.server.socket.ServerContext,
	 * byte[], com.absir.server.socket.SocketBuffer)
	 */
	@Override
	public Serializable register(SocketChannel socketChannel, ServerContext serverContext, byte[] buffer, SocketBuffer socketBuffer)
			throws Throwable {
		String[] params = new String(buffer).split(",", 16);
		if (params.length >= 2) {
			if(params.length > 11 && buffer.length == 16) {
				return params[1] + ',' + socketChannel.socket().getInetAddress().getHostAddress();
			}
			
			byte[] secerets = KernelByte.getLengthBytes(socketChannel.hashCode());
			String validate = HelperEncrypt.encryptionMD5(MasterService.ME.getKey(), secerets);
			if (validate.equals(params[0])) {
				String id = params[1] + ',' + socketChannel.socket().getInetAddress().getHostAddress();
				socketBuffer.setServerContext(register(id, params, socketChannel, serverContext, buffer));
				return id;
			}
		}
		return null;
	}

	/**
	 * @param id
	 * @param params
	 * @param socketChannel
	 * @param serverContext
	 * @param buffer
	 * @return
	 * @throws Throwable
	 */
	protected ServerContext register(String id, String[] params, SocketChannel socketChannel, ServerContext serverContext,
			byte[] buffer) throws Throwable {
		return MasterService.ME.getMasterReceiverContext().getServerContext();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.absir.server.socket.resolver.SocketSessionResolver#doBeat(java.io
	 * .Serializable, java.nio.channels.SocketChannel,
	 * com.absir.server.socket.ServerContext)
	 */
	@Override
	public boolean doBeat(Serializable id, SocketChannel socketChannel, IServerContext serverContext) {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.absir.server.socket.resolver.SocketSessionResolver#unRegister(java
	 * .io.Serializable, java.nio.channels.SocketChannel,
	 * com.absir.server.socket.ServerContext,
	 * com.absir.server.socket.SocketChannelContext)
	 */
	@Override
	public void unRegister(Serializable id, SocketChannel socketChannel, IServerContext serverContext,
			SocketChannelContext socketChannelContext) throws Throwable {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.absir.appserv.system.master.MasterSessionResolver#registerDone(java
	 * .io.Serializable, java.lang.String, java.nio.channels.SocketChannel)
	 */
	@Override
	public void registerDone(Serializable id, String key, SocketChannel socketChannel) {
	}
}
